<?php

declare( strict_types = 1 );

namespace App\Command;

use App\Common as com;
use Hyperf\Command\Command as HyperfCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Hyperf\Utils\Coroutine;
use Hyperf\Command\Event;

abstract class Base extends HyperfCommand {

	/**
	 * @return void
	 */
	public function configure():void {
		//
		parent::configure();
		$this->setDescription( $this->name . ' Command' );
	}

	/**
	 * 处理
	 * @return void
	 */
	public function handle():void {
		$this->handleAsPanel( function(){
			if( method_exists( $this, 'handleRun' ) ){
				$this->handleRun();
			}
		} );
	}

	/**
	 * 运行面板
	 * @param \Closure $runFn
	 */
	protected function handleAsPanel( \Closure $runFn ) {
		$this->echoPanelInfo();
		//
		try{
			call_user_func( $runFn );
		} catch( \Throwable $e ){
			$this->echoLineAsError( '发生异常错误' );
			$this->echoLineAsLog( '========== exception data ==========' );
			com\Lib\Err\Exception::showSimpleShowExceptionInfo( $e );
			$this->echoLineAsLog( '========== - ==========' );
		}
		//
		$this->echoLineAsLog( 'Exit' );
	}

	/**
	 * 输出命令面板信息
	 * @return void
	 */
	protected function echoPanelInfo() {
		$this->echoLineAsLog( '========== Run ==========' );
		$this->echoLineAsLog( '> name: ' . $this->name );
		$this->echoLineAsLog( '> status: start run...' );
		$this->echoLineAsLog( '========== Log ==========' );
	}

	/**
	 * 守护
	 * @param \Closure $runFn 执行函数 函数签名：runFn():bool|null [null]继续运行 [true]执行完成，结束继续运行 [false]发生错误，结束继续执行
	 * @param int|null $retryNum 重试次数 [null][默认]无限
	 * @param float $retryIntervalS 重试间隔，单位：秒
	 * @return bool [false]执行失败或者超过重试次数
	 */
	protected function handleAsDemons( \Closure $runFn, ?int $retryNum = null, float $retryIntervalS = 1 ):bool {
		$this->echoDemonsInfo( $retryNum, $retryIntervalS );
		//
		$currentRetryNum = 0;
		//
		while( true ){
			try{
				$fnRes = call_user_func( $runFn );
				if( $fnRes !== null ){
					$this->echoLineAsLog( "执行函数返回：{$fnRes}，守护程序退出。" );
					return $fnRes;
				}
			} catch( \Throwable $e ){
				com\Lib\Err\Exception::showSimpleShowExceptionInfo( $e );
			}
			// 重试次数
			if( $retryNum !== null ){
				if( $currentRetryNum >= $retryNum ){
					$this->echoLineAsError( '已超过最大重试次数，守护程序退出。' );
					return false;
				}
				//
				$currentRetryNum++;
			}
			//一秒后重启
			\Swoole\Coroutine::sleep( $retryIntervalS );
			//
			$this->echoLineAsLog( "重启demons，当前已重启 {$currentRetryNum} 次，最大重试次数为：" . $retryNum !== null ? $retryNum : "" );
		}
	}

	/**
	 * 输出命令面板信息
	 * @param int|null $retryNum 重试次数 [null][默认]无限
	 * @param float $retryIntervalS 重试间隔，单位：秒
	 * @return void
	 */
	protected function echoDemonsInfo( int $retryNum = null, float $retryIntervalS = 1 ):void {
		$this->echoLineAsLog( '========== run ==========' );
		$this->echoLineAsLog( '> name: ' . $this->name );
		$this->echoLineAsLog( '> runType: Demons' );
		$this->echoLineAsLog( '> retryNum: ' . $retryNum ?? '无限' );
		$this->echoLineAsLog( '> retryIntervalS: ' . $retryIntervalS );
		$this->echoLineAsLog( '> status: Start run...' );
		$this->echoLineAsLog( '=========================' );
	}

	/**
	 * 输出一行日志
	 * @param $logData
	 * @return void
	 */
	protected function echoLineAsLog( $logData ):void {
		$this->line( "> Log: {$logData}" );
	}

	/**
	 * 输出一行错误
	 * @param $logData
	 * @return void
	 */
	protected function echoLineAsError( $logData ):void {
		$this->line( "> Error: {$logData}" );
	}

	/**
	 * 记录debug日志
	 * @param $logData
	 * @return int
	 */
	protected function recordDebugLog( $logData ):int {
		com\Lib\Debug::newLog()->setLogSid( 'debugLog.' . $this->name )->createLog( $logData );
	}

}